﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace thinger.ModbusRTULib
{
    public class ModbusRTU
    {
        #region 字段或属性

        /// <summary>
        /// 串口通信对象
        /// </summary>
        private SerialPort serialPort;

        /// <summary>
        /// 读取超时时间为2000
        /// </summary>
        public int ReadTimeOut { get; set; } = 2000;

        /// <summary>
        /// 写入超时时间
        /// </summary>
        public int WriteTimeOut { get; set; } = 2000;

        /// <summary>
        /// 每次串口通信前的延时时间为10
        /// </summary>
        public int SleepTime { get; set; } = 10;

        /// <summary>
        /// 最大接收时间为5000
        /// </summary>
        public int ReceiveTimeOut { get; set; } = 5000;

        /// <summary>
        /// Dtr使能标志
        /// </summary>
        private bool dtrEnable=false;

        /// <summary>
        /// Dtr使能标志
        /// </summary>
        public bool DtrEnable
        {
            get { return dtrEnable; }
            set { 
                dtrEnable = value;
                serialPort.DtrEnable = value;
            }
        }

        /// <summary>
        /// Rtr使能标志
        /// </summary>
        private bool rtsEnable;

        /// <summary>
        /// Rtr使能标志
        /// </summary>
        public bool RtsEnable
        {
            get { return rtsEnable; }
            set { rtsEnable = value; 
                serialPort.RtsEnable = value;
            }
        }

        #endregion


        #region 构造方法

        /// <summary>
        /// 构造器
        /// </summary>
        public ModbusRTU()
        {
            serialPort = new SerialPort();

          
        }

        #endregion


        #region 建立连接和断开连接

        /// <summary>
        /// 建立连接
        /// </summary>
        /// <param name="portName">串口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">校验位</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        /// <returns>返回布尔，表示是否成功</returns>
        public bool Connect(string portName, int baudRate=9600, Parity parity=Parity.None, int dataBits=8, StopBits stopBits= StopBits.None)
        {
            // 串口打开时
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
            }

            serialPort.PortName = portName;
            serialPort.BaudRate = baudRate;
            serialPort.Parity = parity;
            serialPort.DataBits = dataBits;
            serialPort.StopBits = stopBits;

            serialPort.ReadTimeout = ReadTimeOut;
            serialPort.WriteTimeout = WriteTimeOut;

            try
            {
                serialPort.Open();

            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void DisConnect()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
            }
        }

        #endregion


        #region CRC校验

        private static readonly byte[] aucCRCHi =
        {
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
            0x00,0xC1,0x81,0x40
        };

        private static readonly byte[] aucCRCLo =
        {
            0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,
            0x05,0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,
            0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,0xD8,0x18,0x19,0xD9,
            0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
            0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,
            0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,
            0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,0x3C,0xFC,0xFD,0x3D,
            0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
            0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,
            0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
            0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,0x61,0xA1,
            0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
            0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,
            0x69,0xA9,0xA8,0x68,0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,
            0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,
            0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
            0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,
            0x55,0x95,0x94,0x54,0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,
            0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,0x88,0x48,0x49,0x89,
            0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
            0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,
            0x41,0x81,0x80,0x40
        };

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="pucFrame">报文(无校验码的)</param>
        /// <param name="usLen">报文长度(无校验码的)</param>
        /// <returns></returns>
        private byte[] CRC16(byte[] pucFrame, int usLen)
        {
            int i = 0;
            byte[] res = new byte[2] { 0xFF, 0xFF };
            ushort iIndex;
            while (usLen-- > 0) {
                iIndex = (ushort)(res[0] ^ pucFrame[i++]);
                res[0] = (byte)(res[1] ^ aucCRCHi[iIndex]);
                res[1] = aucCRCLo[iIndex];
            }
            return res;
        }

        /// <summary>
        /// 检查校验码是否正确
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool CheckCRC(byte[] value)
        {
            if (value == null) return false;
            if (value.Length <= 2) return false;

            int length = value.Length;
            byte[] buf = new byte[length - 2];
            Array.Copy(value, 0, buf, 0, buf.Length);

            byte[] CRCbuf = CRC16(buf, buf.Length);

            if (CRCbuf[0] == value[length - 2] && CRCbuf[1] == value[length - 1])
            {
                return true;
            }
            return false;
        }

        #endregion


        #region 发送并接收方法

        /// <summary>
        /// 发送报文并接收报文
        /// </summary>
        /// <param name="send">发送字节数组报文</param>
        /// <param name="receive">接收字节数组报文</param>
        /// <returns>是否成功发送并接收报文</returns>
        public bool SendAndReceive(byte[] send, ref byte[] receive)
        {
            try
            {
                // 发送报文
                serialPort.Write(send, 0, send.Length);

                // 定义一个Buffer
                byte[] buffer = new byte[1024];

                // 定义一个内存
                MemoryStream stream = new MemoryStream();

                // 定义一个开始时间
                DateTime start = DateTime.Now;

                // 这么处理的原因是为了防止一次性读不完整

                // 循环读取缓冲区的数据，如果大于0，就读出来，放到内存里，如果等于0，说明读完了

                while (true)
                {
                    Thread.Sleep(SleepTime);

                    if (serialPort.BytesToRead > 0)
                    {
                        int count = serialPort.Read(buffer, 0, buffer.Length);

                        stream.Write(buffer, 0, count);
                    }
                    else
                    {
                        if (stream.Length > 0)
                        {
                            break;
                        }
                        else if ((DateTime.Now - start).TotalMilliseconds > ReceiveTimeOut)
                        {
                            return false;
                        }
                    }
                }

                receive = stream.ToArray();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        #endregion


        #region 01读取输出线圈

        /// <summary>
        /// 读取输出线圈
        /// </summary>
        /// <param name="slaveId">站地址</param>
        /// <param name="start">起始线圈地址</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据</returns>
        public byte[] ReadOutputCoils(byte slaveId, ushort start, ushort length)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            // 从站地址+功能码+开始线圈+线圈数量+CRC

            // 从站地址
            SendCommand.Add(slaveId);

            // 功能码
            SendCommand.Add(0x01);

            // 起始线圈地址
            SendCommand.Add((byte)(start / 256));
            SendCommand.Add((byte)(start % 256));

            // 线圈数量
            SendCommand.Add((byte)(length / 256));
            SendCommand.Add((byte)(length % 256));

            // 校验码
            byte[] crc = CRC16(SendCommand.ToArray(), SendCommand.Count);
            SendCommand.AddRange(crc);

            // ②发送报文


            // ③接收报文
            byte[] receive = null;

            int byteLength = length % 8 == 0 ? length / 8 : length / 8 + 1;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④验证报文
                if (CheckCRC(receive) && receive.Length == 5 + byteLength)
                {
                    if (receive[0] == slaveId && receive[1] == 0x01 && receive[2] == byteLength)
                    {
                        // ⑤解析报文
                        byte[] result = new byte[byteLength];

                        Array.Copy(receive, 3, result, 0, byteLength);

                        return result;

                    }

                }

            }

            return null;
        }

        #endregion


        #region 02读取输入线圈

        /// <summary>
        /// 读取输入线圈
        /// </summary>
        /// <param name="slaveId">站地址</param>
        /// <param name="start">起始线圈地址</param>
        /// <param name="length">长度</param>
        /// <returns>返回数据</returns>
        public byte[] ReadInputCoils(byte slaveId, ushort start, ushort length)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            // 从站地址+功能码+开始线圈+线圈数量+CRC

            // 从站地址
            SendCommand.Add(slaveId);

            // 功能码
            SendCommand.Add(0x02);

            // 起始线圈地址
            SendCommand.Add((byte)(start / 256));
            SendCommand.Add((byte)(start % 256));

            // 线圈数量
            SendCommand.Add((byte)(length / 256));
            SendCommand.Add((byte)(length % 256));

            // 校验码
            byte[] crc = CRC16(SendCommand.ToArray(), SendCommand.Count);
            SendCommand.AddRange(crc);

            // ②发送报文


            // ③接收报文
            byte[] receive = null;

            int byteLength = length % 8 == 0 ? length / 8 : length / 8 + 1;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④验证报文
                if (CheckCRC(receive) && receive.Length == 5 + byteLength)
                {
                    if (receive[0] == slaveId && receive[1] == 0x02 && receive[2] == byteLength)
                    {
                        // ⑤解析报文
                        byte[] result = new byte[byteLength];

                        Array.Copy(receive, 3, result, 0, byteLength);

                        return result;

                    }

                }

            }

            return null;
        }




        #endregion


        #region 03读取输出寄存器

        /// <summary>
        /// 读取输出寄存器
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">初始寄存器地址</param>
        /// <param name="length">寄存器数量</param>
        /// <returns>返回字节数组</returns>
        public byte[] ReadOutputRegisters(byte slaveld, ushort start, ushort length)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            // 从站地址+功能码+寄存器开始地址+寄存器数量+校验码

            // 从站地址
            SendCommand.Add(slaveld);

            // 功能码
            SendCommand.Add(0x03);

            // 寄存器起始地址
            SendCommand.Add((byte)(start / 256));
            SendCommand.Add((byte)(start % 256));

            // 寄存器数量
            SendCommand.Add(((byte)(length / 256)));
            SendCommand.Add(((byte)(length % 256)));

            // 校验码
            SendCommand.AddRange(CRC16(SendCommand.ToArray(), SendCommand.Count));

            // ②发送报文

            // ③接收报文

            byte[] receive = null;

            int byteLength = 2 * length;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④校验报文
                if (CheckCRC(receive) && receive.Length == 5 + byteLength)
                {
                    if (receive[0] == slaveld && receive[1] == 0x03 && receive[2] == byteLength)
                    {
                        // ⑤解析报文

                        byte[] result = new byte[byteLength];

                        Array.Copy(receive, 3, result, 0, byteLength);

                        return result;
                    }

                }


            }

            return null;


        }

        #endregion


        #region 04读取输入寄存器

        /// <summary>
        /// 读取输入寄存器
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">初始寄存器地址</param>
        /// <param name="length">寄存器数量</param>
        /// <returns>返回字节数组</returns>
        public byte[] ReadInputRegisters(byte slaveld, ushort start, ushort length)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            // 从站地址+功能码+寄存器开始地址+寄存器数量+校验码

            // 从站地址
            SendCommand.Add(slaveld);

            // 功能码
            SendCommand.Add(0x04);

            // 寄存器起始地址
            SendCommand.Add((byte)(start / 256));
            SendCommand.Add((byte)(start % 256));

            // 寄存器数量
            SendCommand.Add(((byte)(length / 256)));
            SendCommand.Add(((byte)(length % 256)));

            // 校验码
            SendCommand.AddRange(CRC16(SendCommand.ToArray(), SendCommand.Count));

            // ②发送报文

            // ③接收报文

            byte[] receive = null;

            int byteLength = 2 * length;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④校验报文
                if (CheckCRC(receive) && receive.Length == 5 + byteLength)
                {
                    if (receive[0] == slaveld && receive[1] == 0x04 && receive[2] == byteLength)
                    {
                        // ⑤解析报文

                        byte[] result = new byte[byteLength];

                        Array.Copy(receive, 3, result, 0, byteLength);

                        return result;
                    }

                }


            }

            return null;


        }

        #endregion


        #region 05写入单个线圈(预置)

        /// <summary>
        /// 写入单个线圈
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">线圈地址</param>
        /// <param name="value">线圈值</param>
        /// <returns>是否成功</returns>
        public bool PreSetSingleCoil(byte slaveld, ushort start, bool value)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            // 从站地址 + 功能码 + 线圈地址 + 线圈值 + 校验码

            // 从站地址
            SendCommand.Add(slaveld);

            // 功能码
            SendCommand.Add(0x05);

            // 线圈地址
            SendCommand.Add((byte)(start / 256));
            SendCommand.Add((byte)(start % 256));

            // 线圈值
            SendCommand.Add(value?(byte)0xFF:(byte)0x00);
            SendCommand.Add(0x00);

            // 校验码
            SendCommand.AddRange(CRC16(SendCommand.ToArray(), SendCommand.Count));

            // ②发送报文

            // ③接收报文

            byte[] receive = null;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④校验报文
                if (CheckCRC(receive) && receive.Length == 8)
                {
                    return ByteArrayEquals(SendCommand.ToArray(), receive);
                }

            }

            return false;
        }

        #endregion


        #region 06写入单个寄存器

        /// <summary>
        /// 写入单个寄存器
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">寄存器地址</param>
        /// <param name="value">寄存器值(两个字节)</param>
        /// <returns>是否成功</returns>
        public bool PreSetSingleRegister(byte slaveld, ushort start, byte[] value)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            // 从站地址 + 功能码 + 寄存器地址 + 寄存器值 + 校验码

            // 从站地址
            SendCommand.Add(slaveld);

            // 功能码
            SendCommand.Add(0x06);

            // 地址
            SendCommand.Add((byte)(start / 256));
            SendCommand.Add((byte)(start % 256));

            // 线圈值
            SendCommand.AddRange(value);

            // 校验码
            SendCommand.AddRange(CRC16(SendCommand.ToArray(), SendCommand.Count));

            // ②发送报文

            // ③接收报文

            byte[] receive = null;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④校验报文
                if (CheckCRC(receive) && receive.Length == 8)
                {
                    return ByteArrayEquals(SendCommand.ToArray(), receive);
                }

            }

            return false;
        }

        /// <summary>
        /// 写入单个寄存器
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">寄存器地址</param>
        /// <param name="value">ushort类型</param>
        /// <returns>是否成功</returns>
        public bool PreSetSingleRegister(byte slaveld, ushort start, ushort value)
        {
            return PreSetSingleRegister(slaveld, start, BitConverter.GetBytes(value));
        }

        /// <summary>
        /// 写入单个寄存器
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">寄存器地址</param>
        /// <param name="value">short类型</param>
        /// <returns>是否成功</returns>
        public bool PreSetSingleRegister(byte slaveld, ushort start, short value)
        {
            return PreSetSingleRegister(slaveld, start, BitConverter.GetBytes(value));
        }

        #endregion


        #region 0F写入多个线圈
        /// <summary>
        /// 写入多个线圈
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">初始线圈地址</param>
        /// <param name="value">线圈数据</param>
        /// <returns></returns>
        public bool PreSetMultiCoils(byte slaveld, ushort start, bool[] value)
        {
            // ①拼接报文
            List<byte> SendCommand = new List<byte>();

            byte[] setArray = GetByteArrayFromBoolArray(value);

            // 从站地址+功能码+线圈起始地址+线圈数+字节计数+数据+CRC

            // 从站地址
            SendCommand.Add(slaveld);

            // 功能码
            SendCommand.Add(0x0F);

            // 线圈起始地址
            SendCommand.Add((byte)(start/256));
            SendCommand.Add((byte)(start%256));

            // 线圈数
            SendCommand.Add(((byte)(value.Length/256)));
            SendCommand.Add(((byte)(value.Length%256)));

            // 字节计数
            SendCommand.Add((byte)setArray.Length);

            // 数据
            SendCommand.AddRange(setArray);

            // 校验码
            SendCommand.AddRange(CRC16(SendCommand.ToArray(), SendCommand.Count));

            // ②发送报文

            // ③接收报文
            byte[] receive = null;

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // 验证报文
                if (CheckCRC(receive) && receive.Length == 8)
                {
                    for (int i = 0; i < 6; i++)
                    {
                        if (SendCommand[i] != receive[i])
                        {
                            return false;
                        }
                    }

                    return true;
                }
            }

            return false;


            // ④解析报文
        }

        #endregion


        #region 10写入多个寄存器

        /// <summary>
        /// 写入多个寄存器
        /// </summary>
        /// <param name="slaveld">从站地址</param>
        /// <param name="start">起始寄存器地址</param>
        /// <param name="values">数据</param>
        /// <returns></returns>
        public bool PreSetMultiRegisters(byte slaveld, ushort start, byte[] values)
        {
            // ①拼接报文
            if (values == null || values.Length == 0 || values.Length % 2 == 1)
            {
                return false;
            }

            // 寄存器数量
            int RegisterLength = values.Length / 2; 

            // 从站地址+功能码+起始寄存器地址+寄存器数量+字节计数+数据+CRC

            List<byte> SendCommand = new List<byte>();

            // 从站地址
            SendCommand.Add(slaveld);

            // 功能码
            SendCommand.Add(0x10);

            // 起始寄存器地址
            SendCommand.Add((byte)(start/256));
            SendCommand.Add((byte)(start%256));

            // 寄存器数量
            SendCommand.Add((byte)(RegisterLength/256));
            SendCommand.Add((byte)(RegisterLength%256));

            // 字节计数
            SendCommand.Add(((byte)values.Length));

            // 数据
            SendCommand.AddRange(values);

            // 校验码
            SendCommand.AddRange(CRC16(SendCommand.ToArray(), SendCommand.Count));

            // ②发送报文

            // ③接收报文
            byte[] receive = SendCommand.ToArray();

            if (SendAndReceive(SendCommand.ToArray(), ref receive))
            {
                // ④验证报文
                if (CheckCRC(receive) && receive.Length == 8)
                {
                    // 验证发送和接收的前六个字节是否相同

                    for (int i = 0; i < 6; i++)
                    {
                        if (SendCommand[i] != receive[i])
                        {
                            return false;
                        }
                    }

                    return true;
                }
            }

            return false;
        }

        #endregion


        #region 数组比较方法

        private bool ByteArrayEquals(byte[] b1, byte[] b2)
        {
            if (b1 == null || b2 == null) return false;

            if (b1.Length != b2.Length) return false;

            for (int i = 0; i < b1.Length; i++)
            {
                if (b1[i] != b2[i])
                {
                    return false;
                }
            }

            return true;
        }


        #endregion


        #region 将布尔数组转换成字节数组
        /// <summary>
        /// 将布尔数组转换成字节数组
        /// </summary>
        /// <param name="value">布尔数组</param>
        /// <returns></returns>
        private byte[] GetByteArrayFromBoolArray(bool[] value)
        {
            int byteLength = value.Length % 8 == 0 ? value.Length / 8 : value.Length / 8 + 1;

            byte[] result = new byte[byteLength];

            for (int i = 0; i < result.Length; i++)
            {
                // 获取每个字节的值

                // 计算当前字节需要处理的位数
                int total = value.Length < 8 * (i + 1) ? value.Length - 8 * i : 8;

                for (int j = 0; j < total; j++)
                {
                    result[i] = SetBitValue(result[i], j, value[8 * i + j]);
                }
            }

            return result;
        }

        /// <summary>
        /// 将某个字节某个位 置位或复位
        /// </summary>
        /// <param name="src">原始字节值</param>
        /// <param name="bit">设置的索引</param>
        /// <param name="value">要设置的值</param>
        /// <returns></returns>
        private byte SetBitValue(byte src, int bit, bool value)
        {
            return value ? (byte)(src | (byte)Math.Pow(2, bit)) : (byte)(src & ~(byte)Math.Pow(2, bit));
        }

        #endregion


    }
}
